﻿using EmbeddedLanguage;
using System.Collections.Generic;
using System;
using System.Linq.Expressions;
using EmbeddedLanguage.Attributes;

namespace EmbeddedLangTest
{

    public class NumberInfo : IHaveOnNew<NumberInfo>
    {
        public int Val;

        //public ActionList<NumberInfo> OnNew { set { value.ForEach(action => action(this)); } }
        public ActionList<NumberInfo> OnNew { set { this.OnNew(value);}}
        public Expression GetMethodBind()
        {
            return this.MethodBind;
        }

        #region IsPrime
        public Func<bool> IsPrime;

        //public bool IsPrime() {return false; }

        public static Expression<Func<NumberInfo, bool>> NumberInfoIsPrime_expr = numberInfo =>
            numberInfo.Val < 2
                ? false
                :
            Core<bool>.IntLoopSearch(2, numberInfo.Val.Sqrt().ToInt() + 1,
                //if
                i => numberInfo.Val % i == 0,
                //then
                i => false,
                //else
                () => true
            )
        ;

        public static Func<NumberInfo, bool> NumberInfoIsPrime;
        #endregion

        #region Add
        
        public static Expression<Func<NumberInfo, int, NumberInfo>> NumberInfoAdd_expr = (numberInfo, i) =>
            numberInfo.Assign(out numberInfo.Val, numberInfo.Val + i)
        ;

        public static Func<NumberInfo, int, NumberInfo> NumberInfoAdd;

        public Func<int, NumberInfo> Add;
        #endregion

        #region Register Static Funcs
        private static Expression<Action<NumberInfo>> __NumberInfo = numberInfo => numberInfo
            .AssignStaticFunc_1x1(out NumberInfoIsPrime, NumberInfo.NumberInfoIsPrime_expr)
            .AssignStaticFunc_2x1(out NumberInfoAdd, NumberInfo.NumberInfoAdd_expr)
        ;

        static NumberInfo()
        {
            NumberInfoIsPrime = NumberInfoIsPrime_expr.Compile();
           __NumberInfo.Compile().Invoke(null);
        }
        #endregion


        public Expression<Action<NumberInfo>> MethodBind
        {
            get {
                return numInfo =>
                    numInfo
                        .AssignStaticMethod_0x1(out numInfo.IsPrime, () => NumberInfoIsPrime(this))
                        .AssignStaticMethod_1x1(out numInfo.Add, addend => NumberInfoAdd(this, addend))
                ;
            }
        }

        
    }


    
}
